#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <process.h>

#define BUF_SIZE 100
#define MAX_CLNT 256

void SendMsg(char *arg, int len);
unsigned WINAPI HandleClnt(void *arg);
void error_handling(char *msg);

int clntCnt = 0;
SOCKET clntSocks[MAX_CLNT];
HANDLE hMutex;

int main(int argc, char *argv[])
{
    WSADATA wsaData;
    SOCKET hServSock, hClntSock;
    SOCKADDR_IN servAdr, clntAdr;
    int clntAdrSz;
    HANDLE hThread;

    if (argc != 2)
    {
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }

    if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        error_handling("WSAStartup() error!");

    hMutex = CreateMutex(NULL, FALSE, NULL);
    hServSock = socket(PF_INET, SOCK_STREAM, 0);

    memset(&servAdr, 0, sizeof(servAdr));
    servAdr.sin_family = AF_INET;
    servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
    servAdr.sin_port = htons(atoi(argv[1]));

    if (bind(hServSock, (SOCKADDR *)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
        error_handling("bind() error");
    if (listen(hServSock, 5) == SOCKET_ERROR)
        error_handling("listen() error");

    while (1)
    {
        clntAdrSz = sizeof(clntAdr);
        hClntSock = accept(hServSock, (SOCKADDR *)&clntAdr, &clntAdrSz);

        WaitForSingleObject(hMutex, INFINITE);          //上锁
        clntSocks[clntCnt++] = hClntSock; //写入新连接
        ReleaseMutex(hMutex);        //解锁

        hThread = (HANDLE)_beginthreadex(NULL, 0, HandleClnt, (void *)&hClntSock, 0, NULL);
        printf("Connected client IP: %s \n", inet_ntoa(clntAdr.sin_addr)); //客户端连接的ip地址
    }
    closesocket(hServSock);
    WSACleanup();
    return 0;
}

unsigned WINAPI HandleClnt(void *arg)
{
    SOCKET hClntSock = *((SOCKET *)arg);
    int str_len = 0, i;
    char msg[BUF_SIZE];

    while ((str_len = recv(hClntSock, msg, sizeof(msg), 0)) != 0)
        SendMsg(msg, str_len);

    //接收到消息为0，代表当前客户端已经断开连接

    WaitForSingleObject(hMutex, INFINITE);
    for (i = 0; i < clntCnt; i++) //删除没有连接的客户端
    {
        if (hClntSock == clntSocks[i])
        {
            while (i++ < clntCnt - 1)
                clntSocks[i] = clntSocks[i + 1];
            break;
        }
    }
    clntCnt--;
    ReleaseMutex(hMutex);
    closesocket(hClntSock);
    return 0;
}

void SendMsg(char *msg, int len) //向连接的所有客户端发送消息
{
    int i;
    WaitForSingleObject(hMutex, INFINITE);
    for (i = 0; i < clntCnt; i++)
        send(clntSocks[i], msg, len, 0);
    ReleaseMutex(hMutex);
}

void error_handling(char *msg)
{
    fputs(msg, stderr);
    fputc('\n', stderr);
    exit(1);
}